#ifndef DISCONNECT_LOGGER_H
#define DISCONNECT_LOGGER_H

#include <QObject>
#include <QFile>
#include <QTextStream>
#include <QJsonObject>
#include <QJsonDocument>
#include <QDateTime>
#include <QMutex>
#include <QDir>
#include <QCoreApplication>

enum class DisconnectType {
    HeartbeatTimeout,      // 心跳超时
    RegisterTimeout,       // 注册超时
    DatabaseTimeout,       // 数据库超时
    ManualDisconnect,      // 手动断开
    SocketError,           // Socket错误
    NetworkError,          // 网络错误
    UserRequest,           // 用户请求
    SystemShutdown,        // 系统关闭
    Unknown                // 未知原因
};

enum class DisconnectResult {
    Success,               // 断开成功
    Failed,                // 断开失败
    PartialSuccess,        // 部分成功
    Timeout,               // 超时
    Error                    // 错误
};

struct DisconnectLogEntry {
    QString timestamp;
    DisconnectType disconnectType;
    QString disconnectTypeStr;
    QString triggerReason;
    QString connectionId;
    QString userId;
    QString robotSN;
    QString clientAddress;
    int clientPort;
    DisconnectResult result;
    QString resultStr;
    QString contextInfo;
    qint64 connectionDuration;  // 连接持续时间（毫秒）
    int heartbeatCount;         // 心跳次数
    QString additionalInfo;     // 额外信息
};

class DisconnectLogger : public QObject {
    Q_OBJECT

public:
    static DisconnectLogger* instance();
    
    void logDisconnect(const DisconnectLogEntry& entry);
    void logDisconnect(DisconnectType type, const QString& reason, 
                      const QString& connectionId = "", const QString& robotSN = "",
                      const QString& clientAddress = "", int clientPort = -1,
                      DisconnectResult result = DisconnectResult::Success,
                      const QString& context = "", qint64 connectionDuration = 0,
                      int heartbeatCount = 0, const QString& additionalInfo = "");
    
    void logHeartbeatTimeout(const QString& robotSN, const QString& clientAddress, 
                           int consecutiveTimeouts, qint64 connectionDuration, int heartbeatCount);
    void logRegisterTimeout(const QString& clientAddress, qint64 connectionDuration);
    void logDatabaseTimeout(const QString& robotSN, const QString& lastPing, qint64 connectionDuration);
    void logManualDisconnect(const QString& robotSN, const QString& clientAddress, 
                           const QString& operatorInfo, qint64 connectionDuration);
    void logSocketError(const QString& robotSN, const QString& clientAddress, 
                       const QString& errorString, qint64 connectionDuration);
    void logUserRequest(const QString& userId, const QString& robotSN, 
                       const QString& reason, qint64 connectionDuration);

private:
    explicit DisconnectLogger(QObject *parent = nullptr);
    ~DisconnectLogger();
    
    DisconnectLogger(const DisconnectLogger&) = delete;
    DisconnectLogger& operator=(const DisconnectLogger&) = delete;
    
    void initializeLogFile();
    QString getLogFileName() const;
    QString disconnectTypeToString(DisconnectType type) const;
    QString disconnectResultToString(DisconnectResult result) const;
    QJsonObject entryToJson(const DisconnectLogEntry& entry) const;
    
private:
    static DisconnectLogger* m_instance;
    QFile* m_logFile;
    QTextStream* m_logStream;
    QMutex m_mutex;
    QString m_currentLogFileName;
};

// 便捷宏定义
#define LOG_DISCONNECT_HEARTBEAT_TIMEOUT(sn, addr, timeouts, duration, count) \
    DisconnectLogger::instance()->logHeartbeatTimeout(sn, addr, timeouts, duration, count)

#define LOG_DISCONNECT_REGISTER_TIMEOUT(addr, duration) \
    DisconnectLogger::instance()->logRegisterTimeout(addr, duration)

#define LOG_DISCONNECT_DATABASE_TIMEOUT(sn, lastPing, duration) \
    DisconnectLogger::instance()->logDatabaseTimeout(sn, lastPing, duration)

#define LOG_DISCONNECT_MANUAL(sn, addr, operatorInfo, duration) \
    DisconnectLogger::instance()->logManualDisconnect(sn, addr, operatorInfo, duration)

#define LOG_DISCONNECT_SOCKET_ERROR(sn, addr, error, duration) \
    DisconnectLogger::instance()->logSocketError(sn, addr, error, duration)

#define LOG_DISCONNECT_USER_REQUEST(userId, sn, reason, duration) \
    DisconnectLogger::instance()->logUserRequest(userId, sn, reason, duration)

#endif // DISCONNECT_LOGGER_H